import { consts, csses } from "@/module-00-codebase/pkg-00-const";
import { Bi } from "@/module-00-codebase/pkg-01-container";
import { Gradient } from "@/module-00-codebase/pkg-08-entity/gradient";
import { ResponsiveLayout } from "@/module-00-codebase/pkg-08-entity/responsive-layout";

import { create } from "jss";
import preset from "jss-preset-default";
export class StyleRenderer {
  render(content: JssContent | JssContent[]): string {
    let result: string;
    if (Array.isArray(content)) {
      result = content.map(c => this.render(c)).join(" ");
    } else if (typeof content === "string") {
      result = content;
    } else if (!!(result = jssCache.get(content))) {
      // skip
    } else if (content instanceof Gradient) {
      const styleDom = document.createElement("style");
      const gradientName = `_${Bi.utils.uuid().replace(/-/g, "")}`;
      styleDom.innerHTML = `@keyframes ${gradientName} { ${generateGradients(content)} }`;
      document.head.appendChild(styleDom);
      result = storeStyleWithJss({ [CN]: { animation: `${gradientName}  ${content.ms || consts.gradientSeconds}ms` } }, content);
    } else if (content instanceof ResponsiveLayout) {
      result = storeStyleWithJss({ [CN]: content.cm, [PC]: { [CN]: content.pc }, [MB]: { [CN]: content.mb } }, content);
    } else {
      result = storeStyleWithJss({ [CN]: content }, content);
    }
    return result;
  }
}
export const initializing = async () => {
  jss = create();
  jss.setup(preset());
};
let jss: ReturnType<typeof create>;
const MIN_PC_WIDTH = 800;
const CN = "temp";
const PC = `@media only screen and (min-width: ${MIN_PC_WIDTH}${csses.UT})`;
const MB = `@media only screen and (max-width: ${MIN_PC_WIDTH - 1}${csses.UT})`;
const jssCache = new Map<any, any>();
const storeStyleWithJss = (styleObj: any, jssContext: any) => {
  const result = jss.createStyleSheet(styleObj).attach().classes[CN];
  jssCache.set(jssContext, result);
  return result;
};
const generateGradients = (context: Gradient) => {
  return context.gradients
    .map(item => {
      const key = item[0];
      const css = item[1];
      const cssKeys = Object.keys(css);
      const styleStrs = cssKeys.map(k => `${k.replace(/[A-Z]/g, $1 => `-${$1.toLowerCase()}`)}:${css[k]};`);
      return `${key * 100}% {${styleStrs.join("")}}`;
    })
    .join(" ");
};
type JssContent = string | { [key: string]: any };
